package com.pl.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

/**
 * 流程一： 直接访问接口一（此时还未登录），认证失败，跳转到 login.html 页面让用户登录，登录会请求接口四，实现用户登录功能，此时 Shiro 已经保存了用户信息了。
 * 流程二： 再次访问接口一（此时用户已经登录），认证成功，跳转到 success.html 页面，展示用户信息。
 * 流程三： 访问接口二，测试角色认证是否成功。
 * 流程四： 访问接口三，测试权限认证是否成功。
 *
 * @author shent
 */
@Controller
@RequestMapping("user")
public class UserController {
    /**
     * 用户登录接口
     * <p>
     * 首先会根据前端传过来的用户名和密码，
     * 创建一个 token，然后使用 SecurityUtils 来创建一个认证主体，
     * 接下来开始调用 subject.login(token) 开始进行身份认证了，
     * 注意这里传了刚刚创建的 token，
     * 就如注释中所述，这一步会跳转到我们自定义的 realm 中，
     * 进入 doGetAuthenticationInfo 方法,就会明白该方法中那个参数 token 了
     *
     * @param user    user
     * @param request request
     * @return string
     */
    @PostMapping("login")
    public String login(User user, HttpServletRequest request) {
        // 根据用户名和密码创建token
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
        // 获取subject认证主体
        Subject subject = SecurityUtils.getSubject();
        try {
            // 开始认证，这一步会跳到我们自定义的realm中
            subject.login(token);
            request.getSession().setAttribute("user", user);
            return "success";
        } catch (Exception e) {
            e.printStackTrace();
            request.getSession().setAttribute("user", user);
            request.setAttribute("error", "用户名或密码错误！");
            return "login";
        }
    }

    /**
     * 身份认证测试接口
     *
     * @param request
     * @return
     */
    @RequestMapping("admin")
    public String admin(HttpServletRequest request) {
        Object user = request.getSession().getAttribute("user");
        return "success";
    }

    /**
     * 角色认证测试接口
     *
     * @param request
     * @return
     */
    @RequestMapping("student")
    public String student(HttpServletRequest request) {
        return "success";
    }

    /**
     * 权限认证测试接口
     *
     * @param request
     * @return
     */
    @RequestMapping("teacher")
    public String teacher(HttpServletRequest request) {
        return "success";
    }
}
